package com.cloud.logger.zchain.zchainclient.http;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloud.logger.zchain.adapter.http.AdapterHttpHeaders;
import com.cloud.logger.zchain.core.common.constant.UUIDGenerator;
import com.cloud.logger.zchain.core.common.entity.AngelaLoggerEntity;
import com.cloud.logger.zchain.core.common.threadlocal.LoggerThreadLocal;
import com.cloud.logger.zchain.zchainclient.util.AngelaAopLogger;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.locks.StampedLock;


/**
 * User: wcy
 * Date: 2017/11/22
 * Time: 16:30
 */
public class RestClientTemplate {
    private static final StampedLock initLock = new StampedLock();

    private static PoolingHttpClientConnectionManager phccm;

    private static String UTF_8 = "UTF-8";

    private static final String  ERROR_MSG = "{\"errCode\":\"8500\"}";

    private static int isAngela = 0;

    private static final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(5000).build();

//    static Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    public static void main(String args[]) {
//        String url = "http://uctenant.drore.com/sso/getRightMenuRecursion.htm?token=v10WK9B625dVwRueGlN1259crdGHTZqS2Q0R3CRdOZm9EVs5Wld8AXXzu3YiBbdAg1VobSUBbVhE%0AcDzj2s1k%2BIt6EwpKqVEwrydMferRPFTyoXOLjhpmOB7QWtzk0zMCZG5UcgTz8bzTEiN%2BXznysjKo%0A%2FzpnLIUqFUCfvbjT8%2BY%3D&sysNum=gis";
//        System.out.println(url = StringUtils.trimAllWhitespace(url));
//        JSONObject obj = new JSONObject();
//        obj.put("a",1);
//        String rrr = HttpUtils.doGet(url);
//        System.out.println(rrr);
    }

    private static void init() {
        long stamp = initLock.writeLock();
        try{
            if (phccm == null) {
                phccm = new PoolingHttpClientConnectionManager();
                phccm.setMaxTotal(5000);// 整个连接池最大连接数
                phccm.setDefaultMaxPerRoute(5);// 每路由最大连接数，默认值是2
            }
        }finally {
            initLock.unlock(stamp);
        }
    }

    private static ArrayList<NameValuePair> covertParams2NVPS(JSONObject params) {

        ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();

        for (Map.Entry<String, Object> param : params.entrySet()) {
            pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));
        }
        return pairs;
    }


    private static CloseableHttpClient getClient(){
        init();
        return HttpClients.custom().setConnectionManager(phccm).build();
    }

    public static String doGet(String url){
        try {
            URL formatUrl = new URL(url);
            URI uri = new URI(formatUrl.getProtocol(), (formatUrl.getHost() +
                    (formatUrl.getPort() == -1 ? "" : ":" + formatUrl.getPort())),
                    formatUrl.getPath(), formatUrl.getQuery(), null);
            HttpGet httpGet = new HttpGet(uri);
            return getResult(httpGet, null);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return ERROR_MSG;
    }


    public static String doGetNotEncoding(String url){
        HttpGet httpGet = new HttpGet(url);
        return getResult(httpGet, null);
    }

    public static String doGetRequest(String url, JSONObject params) throws URISyntaxException {
        URIBuilder ub = new URIBuilder();
        ub.setPath(url);

        ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
        ub.setParameters(pairs);

        HttpGet httpGet = new HttpGet(ub.build());
        return getResult(httpGet, null);
    }

    public static String doGetRequest(String url, JSONObject headers,JSONObject params)
            throws URISyntaxException {
        URIBuilder ub = new URIBuilder();
        ub.setPath(url);

        ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
        ub.setParameters(pairs);

        HttpGet httpGet = new HttpGet(ub.build());
        for (Map.Entry<String, Object> param : headers.entrySet()) {
            httpGet.addHeader(param.getKey(), String.valueOf(param.getValue()));
        }
        return getResult(httpGet, null);
    }

    public static String doPost(String url) {
        HttpPost httpPost = new HttpPost(url);
        return getResult(httpPost, null);
    }

    public static String doPost(String url, JSONObject params) {
        HttpPost httpPost = new HttpPost(url);
        ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
        return getResult(httpPost, params);
    }

    public static String doPost(String message,String url, JSONObject params) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
        return getResult(httpPost, params);
    }

    public static String postForm(String url, JSONObject params){
        try {
            url = StringUtils.trimToEmpty(url);
            HttpPost httpPost = new HttpPost(url);
            ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
            httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));
            return getResult(httpPost, params);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return ERROR_MSG;
    }


    public static JSONObject postForm2Obj(String url,JSONObject parms) {
        url = StringUtils.trimToEmpty(url);
        try {
            String result = postForm(url, parms);
            return JSON.parseObject(result);
        } catch (Exception var8) {
            var8.printStackTrace();
            return JSON.parseObject("{\"errCode\":\"8500\"}");
        }
    }

    private static String getResult(HttpRequestBase request, JSONObject params){
        //添加日志状态
        AngelaLoggerEntity logger = getLogger(request, params);

        long startTime = System.currentTimeMillis();
        CloseableHttpClient httpClient = getClient();

        CloseableHttpResponse response = null;
        try {
            //请求参数设置
            request.setConfig(requestConfig);
            //请求参数添加请求头
            request = addChainNodeToRequest(request);
            response = httpClient.execute(request);
            //添加日志状态
            logger.setStatus(response.getStatusLine().getStatusCode()+"");
            //添加日志状态
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String result = EntityUtils.toString(entity);
                    //添加日志信息
                    logger.setResult(result);
                    return result;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                long endTime = System.currentTimeMillis();
                logger.setElapsedTime(endTime-startTime);
                AngelaAopLogger.loggerHttpClient(logger);
                if(response!=null)
                    response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return ERROR_MSG;
    }

    public static HttpRequestBase addChainNodeToRequest(HttpRequestBase request) {
        String uuid = UUIDGenerator.getUuid();
        request.addHeader(AdapterHttpHeaders.RootId.getName(), LoggerThreadLocal.getLoggerId());
        request.addHeader(AdapterHttpHeaders.NodeId.getName(), uuid);
        request.addHeader(AdapterHttpHeaders.ParentNodeId.getName(), LoggerThreadLocal.getNodeLoggerId());
        LoggerThreadLocal.setNodeId(uuid);
        return request;
    }

    private static AngelaLoggerEntity getLogger(HttpRequestBase request, JSONObject params){
        AngelaLoggerEntity logger = new AngelaLoggerEntity();
        logger.setParentNode(LoggerThreadLocal.getLoggerId());
        logger.setInterfaceName(request.getURI().getPath());
        logger.setSourceIP(request.getURI().getHost());
        logger.setInterfaceIp(request.getURI().toString());
        logger.setInterfacePort(request.getURI().getPort());
        logger.setParms(JSON.toJSONString(params));
        return logger;
    }

}
